<!--人员选择框组件-->
<template>
  <el-dialog v-model="stateDialog" title="人员选择" width="50%" center class="personnelSelection-dialog" @close="closeDialog">
    <div class="dialog-search">
      <el-input v-model="search" placeholder="请输入搜索内容" clearable size="large">
        <template #append>
          <el-button @click="searchBtn">搜索</el-button>
        </template>
      </el-input>
    </div>
    <div class="dialog-menu">
      <div></div>
      <div>
        <el-button @click="checkAll">全选</el-button>
      </div>
      <div>
        <el-button @click="clear">清空</el-button>
      </div>
    </div>
    <div class="dialog-body">
      <!--树形结构页面-->
      <div class="body-left body-box">
        <el-tree lazy :props="props" :load="loadNode" node-key="dn" @node-click="nodeClick" ref="treeRef" />
      </div>
      <!--人员列表页面-->
      <div class="body-center body-box" v-loading="loading" element-loading-text="加载中...">
        <div class="center-item" v-for="(item, index) in personnelList" :key="item.userId" @click="centerBtn(item, index)">
          {{ item.userName }}
        </div>
      </div>
      <!--人员选择页面-->
      <div class="body-right body-box">
        <div class="right-item" v-for="(item, index) in personnelSelection" :key="item.userId" @click="rightBtn(item, index)">
          {{ item.userName }}
        </div>
      </div>
    </div>
    <template #footer>
      <el-button @click="stateDialog = false">关闭</el-button>
      <el-button type="primary" @click="submitBtn">确认</el-button>
    </template>
  </el-dialog>
</template>

<script setup>
const LEVEL = 1; //部门递增层级，每新增一个层级+1
import { getDeptList, getPersonnelInformation } from "@/api/partyBuilding";
import { cloneDeep } from "lodash";
import { ref } from "vue";

const propData = defineProps({
  multipleChoices: {
    type: Boolean,
    required: false,
    default: true,
  }, //是否多选
});
const props = {
  id: "dn", //唯一id
  label: "name", //节点名称
  children: "children", //节点子集
  isLeaf: "leaf", //是否是子节点
}; //树形结构
/**
 * 加载节点
 * @param node 节点
 * @param resolve 添加子节点
 * @returns {*}
 */
const loadNode = async (node, resolve) => {
  const {
    level,
    data: { dn },
  } = node; //解构出层级和当前节点唯一dn
  const { data } = await getDeptList({ level: level + LEVEL, parentDn: dn }); //新增一个层级，所以层级level+1,获取子节点数据
  const nodeData = data.map(item => ({
    dn: item.dn,
    name: item.name,
    leaf: !item.leaf,
    fullName: item.fullName,
  }));
  return resolve(nodeData);
};
const personnelList = ref([]); //人员待选数据
const personnelSelection = ref([]); //人员已选数据
const search = ref(""); //搜索框
const stateDialog = ref(false); //弹窗状态
const loading = ref(false); //加载状态
/**
 * 点击节点时，请求人员信息
 * @param node
 */
const nodeClick = ({ leaf, fullName }) => {
  //当节点是子节点的时候，请求人员列表信息
  getPersonnel({ parentDeptFullName: fullName });
};
/**
 * 请求人员信息
 */
const getPersonnel = async params => {
  loading.value = true;
  const { data } = await getPersonnelInformation(params);
  loading.value = false;
  // 获取已选列表人员的userId的集合
  const userIdsToRemove = new Set(personnelSelection.value.map(item => item.userId));
  // 过滤掉已选列表中有存在于未选列表的人员
  personnelList.value = data.filter(item => !userIdsToRemove.has(item.userId));
};
/**
 * 搜索按钮点击事件
 */
const searchBtn = async () => {
  const params = {
    queryText: search.value,
    maxCount: 20, //默认20条
  };
  await getPersonnel(params);
};
import { ElMessage } from "element-plus";
/**
 * 人员待选框按钮点击事件
 * @param value 选择的人
 * @param index 选择的人索引
 */
const centerBtn = (value, index) => {
  if (propData.multipleChoices || personnelSelection.value.length === 0) {
    personnelList.value.splice(index, 1); //删除人员列表的人员
    personnelSelection.value.push(value); //添加人员列表的人员到人员选择
  } else {
    ElMessage.error("只能单选人员！");
  }
};
/**
 * 人员已选框按钮点击事件
 * @param value 选择的人
 * @param index 选择的人索引
 */
const rightBtn = (value, index) => {
  personnelSelection.value.splice(index, 1); //删除人员列表的人员
  personnelList.value.push(value); //添加人员列表的人员到人员选择
};
/**
 * 人员待选框全选事件
 */
const checkAll = () => {
  personnelSelection.value.push(...personnelList.value); //添加人员列表的人员到人员选择
  personnelList.value = []; //删除人员列表的人员
};
/**
 * 人员已选框清空事件
 */
const clear = () => {
  personnelList.value.push(...personnelSelection.value); //添加人员选择的人员到人员列表
  personnelSelection.value = []; //删除人员选择的人员
};
/**
 * 打开弹窗
 * @param value 弹窗状态
 */
const showDialog = value => {
  stateDialog.value = true;
  personnelSelection.value = cloneDeep(value);
};
const emit = defineEmits(["submit"]);
/**
 * 人员选择提交
 */
const submitBtn = () => {
  emit("submit", personnelSelection.value);
  stateDialog.value = false;
};
const treeRef = ref(null);
/**
 * 关闭弹窗重置数据
 */
const closeDialog = () => {
  personnelList.value = []; //人员待选数据
  personnelSelection.value = []; //人员已选数据
  search.value = ""; //搜索框
  const { root } = treeRef.value.store;
  root.loaded = false;
  root.expand();
};
defineExpose({
  stateDialog,
  showDialog,
});
</script>
<style scoped lang="less">
@import "@/assets/styles/index.less";
.personnelSelection-dialog {
  //菜单页面
  .dialog-search {
    width: 300px;
    margin-bottom: 10px;
    :deep(.el-input) {
      .el-input-group__append {
        color: #fff;
        background-color: @buttonColor;
        cursor: pointer;
      }
    }
  }
  //全选和清空按钮
  .dialog-menu {
    width: 100%;
    display: flex;
    column-gap: 20px;
    margin-bottom: 10px;
    div {
      flex: 1;
      display: flex;
      justify-content: end;
    }
  }
  //人员选择区域
  .dialog-body {
    width: 100%;
    height: 500px;
    display: flex;
    column-gap: 20px;
    .body-box {
      flex: 1;
      border: 1px solid #c3c3c3;
      :deep(.el-icon) {
        color: @buttonColor;
      }
      .el-tree {
        height: 100%;
        overflow-y: auto;
        &::-webkit-scrollbar {
          width: 6px;
        }
        &::-webkit-scrollbar-button {
          display: none;
        }
        &::-webkit-scrollbar-thumb {
          background-color: #dddee0;
          border-radius: 2px;
        }
      }
    }
    .body-center,
    .body-right {
      height: 100%;
      overflow-y: auto;
      &::-webkit-scrollbar {
        width: 6px;
      }
      &::-webkit-scrollbar-button {
        display: none;
      }
      &::-webkit-scrollbar-thumb {
        background-color: #dddee0;
        border-radius: 2px;
      }
      .center-item,
      .right-item {
        display: flex;
        align-items: center;
        height: 30px;
        padding: 10px;
        cursor: pointer;
        &:hover {
          background-color: #eee;
        }
      }
    }
  }
}
</style>
